﻿using CefSharp.WinForms;
using NewLife.Data;
using NewLife.Log;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using XCode;
using XCode.Membership;
using XsDown.Common;

namespace XsDown
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Init();
        }
        Regex urlLiRegex = null;
        Regex urlRegex = null;
        Regex urlRegex2 = null;
        Regex urlRegex3 = null;
        Regex urlRegex4 = null;
        Regex nameRegex = null;

        Regex chaperRx = null;
        Regex chaperNameRx = null;
        Regex chaperUrlRx = null;

        private string urlLiRegexStr = "<li>(?<content>.+?)</li>";
        private string urlRegexStr = "<a.*\">";
        private string urlRegexStr2 = "<a\\s+href=(?<url>.+?)>(?<content>.+?)</a>";
        private string urlRegexStr3 = "<span class=\"s2\"><a\\s+href=(?<url>.+?)>(?<content>.+?)</a>";
        private string urlRegexStr4 = "<span class=\"s4\">(?<content>.+?)</span>";
        //<span class="s2">
        private string nameRegexStr = ">.*</a>";
        //\">[^\\s]*</a>

        private string bookUrlRegexStr = "http://[^\\s]*\"";
        protected string chaperRegex => @"<dd><a\s+href=(?<url>.+?)>(?<content>.+?)</a></dd>";
        private void Init()
        {
            try
            {
                HttpClientX.Instance.FrmHost = frmMain;
                urlLiRegex = new Regex(urlLiRegexStr);
                urlRegex = new Regex(urlRegexStr);
                urlRegex2 = new Regex(urlRegexStr2);
                urlRegex3 = new Regex(urlRegexStr3);
                urlRegex4 = new Regex(urlRegexStr4);
                nameRegex = new Regex(nameRegexStr);
                chaperRx = new Regex(chaperRegex);
                chaperUrlRx = new Regex("href=[^\\s]*html");
                chaperNameRx = new Regex("\">.*</a>");
                QueryData();
            }
            catch (Exception ex)
            {
                XTrace.WriteException(ex);
            }
        }
        int pageIndex = 1;
        int pageSize = 50;
        WhereExpression exp;
        private void QueryData(int pageIndex = 1)
        {
            try
            {
                this.pageIndex = pageIndex;
                if (exp == null)
                    exp = new WhereExpression();
                long count = TXiaoshuo.FindCount(exp);
                PageParameter parameter = new PageParameter() { PageIndex = pageIndex, PageSize = pageSize, OrderBy = TChaperList._.ID, Desc = false };
                var list = TXiaoshuo.FindAll(exp, parameter);
                this.datagridLocal.Dispatcher.Invoke(() =>
                {
                    datagridLocal.ItemsSource = list;
                });
                this.page.Dispatcher.Invoke(() =>
                {
                    page.MaxPage = (int)(count + pageSize - 1) / pageSize;
                    //page.CurrentPage = pageIndex;
                });

            }
            catch (Exception ex)
            {
                NewLife.Log.XTrace.WriteException(ex);
            }
        }

        private void btnDownList_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                string url = txtUrl.Text.Trim();
                Task.Factory.StartNew(new Action(() =>
                {
                    GetUrls(url);
                }));
            }
            catch (Exception ex)
            {
                NewLife.Log.XTrace.WriteException(ex);
            }
        }

        /// <summary>
        /// 获取urls
        /// </summary>
        /// <param name="baseUrl"></param>
        private void GetUrls(string baseUrl, bool display = true)
        {
            try
            {
                string htmlStr = HttpClientX.Instance.GetHtml(baseUrl, "utf8");
                MatchCollection collection = urlRegex2.Matches(htmlStr);
                List<Models.XsUrlInfo> list = new List<Models.XsUrlInfo>();
                if (collection != null && collection.Count > 0)
                {
                    IList<TXiaoshuo> xiaoshuos = new List<TXiaoshuo>();
                    foreach (Match item in collection)
                    {
                        try
                        {
                            Models.XsUrlInfo info = new Models.XsUrlInfo() { SourceID = 0, };
                            string str = item.Value;
                            int hrefIndex = str.IndexOf("href");
                            int hrefEndIndex = str.IndexOf("\"", hrefIndex + 6);
                            string url0 = str.Substring(hrefIndex + 6, hrefEndIndex - hrefIndex - 6);
                            if (!url0.StartsWith("http"))
                                url0 = baseUrl.TrimEnd('/') + url0;
                            info.Url = url0;

                            if (TXiaoshuo.FindCountByUrl(url0) > 0)
                                continue;
                            Match match = nameRegex.Match(str);
                            if (match.Success)
                            {
                                string val = match.Value;
                                info.Name = val.Substring(2, val.Length - 6);
                                if (string.IsNullOrEmpty(info.Name)) continue;
                                if ("'玄幻小说','修真小说','都市小说','穿越小说','网游小说','科幻小说','全部小说'".Contains(info.Name)) continue;
                                TXiaoshuo xiaoshuo = new TXiaoshuo();
                                xiaoshuo.BaseUrl = baseUrl;
                                xiaoshuo.Name = info.Name;
                                xiaoshuo.Url = info.Url;
                                xiaoshuos.Add(xiaoshuo);
                            }
                            list.Add(info);
                        }
                        catch (Exception ee)
                        {
                            NewLife.Log.XTrace.WriteException(ee);
                        }
                    }
                    xiaoshuos.Insert(true);
                    ShowMessage(baseUrl + "加载：" + xiaoshuos.Count);
                }
                if (display)
                {
                    this.datagrid.Dispatcher.Invoke(new Action(() =>
                    {
                        this.datagrid.ItemsSource = list;
                    }));
                }
            }
            catch (Exception ex)
            {

                NewLife.Log.XTrace.WriteException(ex);
            }
        }

        /// <summary>
        /// 获取urls
        /// </summary>
        /// <param name="baseUrl"></param>
        private void GetQuanbenUrls(string baseUrl, bool display = true)
        {
            try
            {
                string htmlStr = HttpClientX.Instance.GetHtml(baseUrl, "utf8");
                MatchCollection collection = urlLiRegex.Matches(htmlStr);
                List<Models.XsUrlInfo> list = new List<Models.XsUrlInfo>();
                if (collection != null && collection.Count > 0)
                {
                    IList<TXiaoshuo> xiaoshuos = new List<TXiaoshuo>();
                    foreach (Match item in collection)
                    {
                        try
                        {
                            string liStr = item.Value;
                            var mathName = urlRegex3.Match(liStr);
                            if (mathName.Success == false)
                                continue;
                            var mathAuthor = urlRegex4.Match(liStr);
                            string str = mathName.Value;
                            string author = mathAuthor.Value;
                            Models.XsUrlInfo info = new Models.XsUrlInfo() { SourceID = 0, };
                            int hrefIndex = str.IndexOf("href");
                            int hrefEndIndex = str.IndexOf("\"", hrefIndex + 6);
                            string url0 = str.Substring(hrefIndex + 6, hrefEndIndex - hrefIndex - 6);
                            if (!url0.StartsWith("http"))
                                url0 = baseUrl.TrimEnd('/') + url0;
                            info.Url = url0;

                            if (TXiaoshuo.FindCountByUrl(url0) > 0)
                                continue;
                            if (!string.IsNullOrEmpty(author) && author.Length > 24)
                            {
                                author = author.Substring(17, author.Length - 24);
                            }
                            Match match = nameRegex.Match(str.Substring(17));
                            if (match.Success)
                            {
                                string val = match.Value;
                                info.Name = val.Substring(2, val.Length - 6);

                                TXiaoshuo xiaoshuo = new TXiaoshuo();
                                xiaoshuo.BaseUrl = baseUrl;
                                xiaoshuo.Name = info.Name;
                                xiaoshuo.Author = author;
                                xiaoshuo.Url = info.Url;
                                xiaoshuos.Add(xiaoshuo);
                            }
                            list.Add(info);
                        }
                        catch (Exception ee)
                        {
                            NewLife.Log.XTrace.WriteException(ee);
                        }
                    }
                    xiaoshuos.Insert(true);
                    ShowMessage(baseUrl + "加载：" + xiaoshuos.Count);
                }
                if (display)
                {
                    this.datagrid.Dispatcher.Invoke(new Action(() =>
                    {
                        this.datagrid.ItemsSource = list;
                    }));
                }
            }
            catch (Exception ex)
            {

                NewLife.Log.XTrace.WriteException(ex);
            }
        }

        private void QueryList(string name)
        {
            string url = "https://www.xbiquge.la/modules/article/waps.php?searchkey=" + name;
            try
            {
                string baseUrl = "https://www.xbiquge.la/";
                //<td class="even">
                Regex regex = new Regex("<td class=\"even\">(?<content>.+?)</td>");

                string htmlStr = HttpClientX.Instance.GetHtml(url, "utf8");
                MatchCollection collection = regex.Matches(htmlStr);
                List<Models.XsUrlInfo> list = new List<Models.XsUrlInfo>();
                if (collection != null && collection.Count > 0)
                {
                    IList<TXiaoshuo> xiaoshuos = new List<TXiaoshuo>();
                    foreach (Match item in collection)
                    {
                        try
                        {
                            Models.XsUrlInfo info = new Models.XsUrlInfo() { SourceID = 0, };
                            string str = item.Value;
                            int hrefIndex = str.IndexOf("href");
                            int hrefEndIndex = str.IndexOf("\"", hrefIndex + 6);
                            string url0 = str.Substring(hrefIndex + 6, hrefEndIndex - hrefIndex - 6);
                            if (!url0.StartsWith("http"))
                                url0 = baseUrl.TrimEnd('/') + url0;
                            info.Url = url0;

                            if (TXiaoshuo.FindCountByUrl(url0) > 0)
                                continue;
                            Match match = nameRegex.Match(str);
                            if (match.Success)
                            {
                                string val = match.Value;
                                info.Name = val.Substring(2, val.Length - 6);

                                TXiaoshuo xiaoshuo = new TXiaoshuo();
                                xiaoshuo.BaseUrl = baseUrl;
                                xiaoshuo.Name = info.Name;
                                xiaoshuo.Url = info.Url;
                                xiaoshuos.Add(xiaoshuo);
                            }
                            list.Add(info);
                        }
                        catch (Exception ee)
                        {
                            NewLife.Log.XTrace.WriteException(ee);
                        }
                    }
                    xiaoshuos.Insert(true);
                    ShowMessage(url + "加载：" + xiaoshuos.Count);
                }

                this.datagrid.Dispatcher.Invoke(new Action(() =>
                {
                    this.datagrid.ItemsSource = list;
                }));

            }
            catch (Exception ex)
            {

                NewLife.Log.XTrace.WriteException(ex);
            }
        }

        private void DownList(int fenlei, int sid, int maxNum)
        {
            if (downing)
                return;
            string url = "https://www.xbiquge.la/fenlei/{0}_{1}.html";
            try
            {
                downing = true;
                for (int i = sid; i < maxNum + 1; i++)
                {
                    string listUrl = string.Format(url, fenlei, i);

                    GetUrls(listUrl, false);
                }

            }
            catch (Exception ex)
            {

                NewLife.Log.XTrace.WriteException(ex);
            }
            finally
            {
                downing = false;
            }
        }

        private void DownWanbenList(int startId, int maxNum)
        {
            if (downing)
                return;
            string url = //"https://www.xbiquge.la/xiaoshuodaquan/{0}";
                "https://www.xbiquwx.la/wanjiexiaoshuo/{0}";
            try
            {
                downing = true;
                for (int i = startId; i < maxNum + 1; i++)
                {
                    string listUrl = string.Format(url, i);

                    GetQuanbenUrls(listUrl, false);
                }

            }
            catch (Exception ex)
            {

                NewLife.Log.XTrace.WriteException(ex);
            }
            finally
            {
                downing = false;
            }
        }
        private IList<TChaperList> DownChapers(TXiaoshuo source)
        {
            try
            {
                if (!source.Url.EndsWith("/"))// || !source.Url.StartsWith(source.BaseUrl))
                    return null;
                NewLife.Data.PageParameter page = new NewLife.Data.PageParameter() { OrderBy = TChaperList._.ID,PageSize=0, Desc = false };
                var oldlist = TChaperList.FindAll(TChaperList._.SourceID == source.ID, page);
                if (oldlist != null && oldlist.Count > 0)
                    return oldlist;
                string htmlStr = HttpClientX.Instance.GetHtml(source.Url, "utf8");
                MatchCollection collection = urlRegex2.Matches(htmlStr);
                List<Models.XsUrlInfo> list = new List<Models.XsUrlInfo>();
                if (collection != null && collection.Count > 0)
                {
                    IList<TChaperList> chaperList = new List<TChaperList>();
                    foreach (Match item in collection)
                    {

                        try
                        {
                            string value = item.Value;
                            string itemUrl = chaperUrlRx.Match(value).Value.Substring(6);
                            string nameStr = chaperNameRx.Match(value).Value;
                            string name = null;
                            if (string.IsNullOrEmpty(nameStr))
                            {
                                nameStr = value.Substring(value.IndexOf("title"), value.IndexOf("\">") - value.IndexOf("title"));
                                name = nameStr.Substring(7).Replace("\">", "");
                            }
                            else
                                name = nameStr.Substring(2, nameStr.Length - 6);
                            TChaperList chaper = new TChaperList() { BaseUrl = source.Url, Name = name, Url = source.Url.TrimEnd('/') + itemUrl, SourceID = source.ID };
                            chaperList.Add(chaper);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }
                    }
                    chaperList.Insert(true);
                    ShowMessage(source.Name + "章节：" + chaperList.Count);
                    return chaperList;
                }


            }
            catch (Exception ex)
            {
                NewLife.Log.XTrace.WriteException(ex);
            }
            return null;
        }
        private void DownChaper(TXiaoshuo source, bool display = false)
        {
            try
            {
                if (!source.Url.EndsWith("/") || !source.Url.StartsWith(source.BaseUrl))
                    return;
                NewLife.Data.PageParameter page = new NewLife.Data.PageParameter() { PageSize = 5, PageIndex = 1 };
                var oldlist = TChaperList.FindAll(TChaperList._.SourceID == source.ID, page);
                if (oldlist != null && oldlist.Count > 0)
                    return;
                var list = new List<Models.XsUrlInfo>();
                var chapers = DownChapers(source);
                if (chapers != null)
                {
                    foreach (var item in chapers)
                    {

                        list.Add(new Models.XsUrlInfo() { Url = item.Url, Name = item.Name });
                    }
                }
                if (display)
                {
                    this.datagrid.Dispatcher.Invoke(new Action(() =>
                    {
                        this.datagrid.ItemsSource = list;
                    }));
                }



            }
            catch (Exception ex)
            {
                NewLife.Log.XTrace.WriteException(ex);
            }
        }
        private void ShowMessage(string msg)
        {
            try
            {
                this.txtInfo.Dispatcher.BeginInvoke(new Action(() =>
                {
                    if (txtInfo.LineCount > 1000)
                        txtInfo.Text = "";
                    txtInfo.AppendText(msg + "\n");
                }));
            }
            catch { }
        }

        private void btnLoadList_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                QueryData();
            }
            catch (Exception ex)
            {
                XTrace.WriteException(ex);
                ShowMessage(ex.Message);
            }
        }

        private void btnDownAll_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                int fenlei = int.Parse(txtFenlei.Text);
                int sid = int.Parse(txtStart.Text);
                int maxNum = int.Parse(txtNum.Text);
                Task.Factory.StartNew(new Action(() =>
                {
                    DownList(fenlei, sid, maxNum);
                }));

            }
            catch (Exception ex)
            {
                XTrace.WriteException(ex);
                ShowMessage(ex.Message);
            }
        }
        bool downing = false;
        private void btnDownAllChaper_Click(object sender, RoutedEventArgs e)
        {

            try
            {
                int fenlei = int.Parse(txtFenlei.Text);
                //XCode.WhereExpression exp = new WhereExpression();
                //NewLife.Data.PageParameter pageParam = new NewLife.Data.PageParameter() { PageIndex = 2, PageSize = 100 };
                //var list = TXiaoshuo.FindAll(exp, pageParam);
                //if (list != null && list.Count > 0)
                //{
                //    DownChaper(list[0],true);
                //}
                //return;
                Task.Factory.StartNew(new Action(() =>
                {
                    DownChapers(fenlei);
                }));

            }
            catch (Exception ex)
            {
                XTrace.WriteException(ex);
                ShowMessage(ex.Message);
            }
        }

        private void DownChapers(int startpage)
        {
            if (downing)
                return;
            try
            {
                downing = true;
                long count = TXiaoshuo.FindCount();
                int page = (int)count / 1000 + 1;
                XCode.WhereExpression exp = new WhereExpression();

                NewLife.Data.PageParameter pageParam = new NewLife.Data.PageParameter() { PageSize = 1000, Sort = TXiaoshuo._.ID };
                for (int i = startpage; i < page; i++)
                {
                    pageParam.PageIndex = i + 1;
                    var list = TXiaoshuo.FindAll(exp, pageParam);
                    if (list != null && list.Count > 0)
                    {
                        for (int j = 0; j < list.Count; j++)
                        {
                            var item = list[j];
                            if (item.IsXiaoshuo == 1)
                                DownChaper(item, false);
                        }
                    }
                }

            }
            catch (Exception ex)
            {
                XTrace.WriteException(ex);
                ShowMessage(ex.Message);
            }
            finally
            {
                downing = false;
            }
        }

        /// <summary>
        /// 内容
        /// </summary>
        protected const string contextRegex = "<div id=\"content\">";
        private string DownXContext(string url)
        {

            string htmlStr = HttpClientX.Instance.GetHtml(url, "utf8");

            int startIndex = htmlStr.IndexOf(contextRegex);
            if (startIndex > 0)
            {
                int endIndex = htmlStr.IndexOf("<!--over-->", startIndex + 27);
                if (endIndex > 0)
                {
                    return htmlStr.Substring(startIndex + 27, endIndex - startIndex - 27).Replace("<br/>", "\r\n").Replace("&nbsp;", " ");
                }
                else
                {
                    endIndex = htmlStr.IndexOf("</div>", startIndex + 27);
                    return htmlStr.Substring(startIndex + 27, endIndex - startIndex - 27).Replace("<br/>", "\r\n").Replace("&nbsp;", " ");
                }
            }

            return null;
        }
        private string DownContext(string url)
        {

            string htmlStr = HttpClientX.Instance.GetHtml(url, "utf8");

            int startIndex = htmlStr.IndexOf(contextRegex);
            if (startIndex > 0)
            {
                int endIndex = htmlStr.IndexOf("<!--over-->", startIndex + 27);
                if (endIndex > 0)
                {
                    return htmlStr.Substring(startIndex + 27, endIndex - startIndex - 27).Replace("<br/>", "\r\n").Replace("<br>","").Replace("&nbsp;", " ");
                }
                else
                {
                    endIndex = htmlStr.IndexOf("</div>", startIndex + 27);
                    return htmlStr.Substring(startIndex + 27, endIndex - startIndex - 27).Replace("<br/>", "\r\n").Replace("<br>", "").Replace("&nbsp;", " ");
                }
            }
            else
            {
                XTrace.WriteLine("下载失败"+url);
            }

            return null;
        }
        private void ShowXSCharps(TXiaoshuo xiaoshuo)
        {

        }

        private void dgmiShow_Click(object sender, RoutedEventArgs e)
        {

            try
            {

                var dg = datagridLocal;
                if (datagrid.IsVisible)
                    dg = datagrid;
                if (dg != null)
                {
                    var xs = dg.SelectedItem as TXiaoshuo;
                    if (xs != null)
                    {
                        Task.Factory.StartNew(() =>
                        {
                            ShowXSCharps(xs);
                        });
                        return;
                    }
                    var item = dg.SelectedItem as Models.XsUrlInfo;
                    if (item != null)
                    {
                        TXiaoshuo xiaoshuo = TXiaoshuo.Find(TXiaoshuo._.Url == item.Url);
                        if (xiaoshuo != null)
                        {
                            ShowXSCharps(xiaoshuo);
                        }
                    }
                }
            }catch(Exception ex)
            {

                XTrace.WriteException(ex);
            }
                        }

        private void dgmiDown_Click(object sender, RoutedEventArgs e)
        {
            try
            {

                var dg = datagridLocal;
                if (datagrid.IsVisible)
                    dg = datagrid;
                if (dg != null)
                {
                    var xs = dg.SelectedItem as TXiaoshuo;
                    if (xs != null)
                    {
                        Task.Factory.StartNew(() =>
                        {
                            DownXiaoshuo(xs);
                        });
                        return;
                    }
                    var item = dg.SelectedItem as Models.XsUrlInfo;
                    if (item != null)
                    {
                        TXiaoshuo xiaoshuo = TXiaoshuo.Find(TXiaoshuo._.Url == item.Url);
                        if (xiaoshuo != null)
                        {

                            Task.Factory.StartNew(() =>
                            {
                                DownXiaoshuo(xs);
                            });
                        }
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                XTrace.WriteException(ex);
            }

        }
        private void DownXiaoshuo(TXiaoshuo xiaoshuo)
        {
            try
            {
                string tempPath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "dowm");
                if (!System.IO.Directory.Exists(tempPath))
                    System.IO.Directory.CreateDirectory(tempPath);

                string filename = System.IO.Path.Combine(tempPath, xiaoshuo.Name + ".txt");
                if (System.IO.File.Exists(filename))
                    return;
                var chapers = DownChapers(xiaoshuo);
                if (chapers != null)
                {
                    using (var fs = File.Create(filename))
                    {
                        for (int i = 0; i < chapers.Count; i++)
                        {
                            var item = chapers[i];
                            string chaperItem = string.Format("【章节】{0}\n", item.Name);
                            ShowMessage(chaperItem);
                            byte[] data = Encoding.UTF8.GetBytes(chaperItem);
                            fs.Write(data, 0, data.Length);
                            string context = DownContext(item.Url);
                            if (context != null)
                            {
                                data = Encoding.UTF8.GetBytes(context + "\n");
                                fs.Write(data, 0, data.Length);
                            }
                            fs.Flush();
                        }
                        fs.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                ShowMessage(xiaoshuo.Name + "下载失败" + ex.Message);
                XTrace.WriteException(ex);
            }
        }

        private void btnDGQuery_Click(object sender, RoutedEventArgs e)
        {
            string name = txtName.Text.Trim();
            string anchor = txtAuthor.Text.Trim();
            exp = new WhereExpression();
            if (!string.IsNullOrEmpty(name))
                exp |= TXiaoshuo._.Name.Contains(name);
            //if(!string.IsNullOrEmpty(anchor))
            //    exp&=TXiaoshuo._.
            QueryData(1);
        }

        private void page_CurrentPageChanged(object sender, Panuon.UI.Core.SelectedValueChangedEventArgs<int> e)
        {
            int id = page.CurrentPage;
            if (id != pageIndex)
            {
                pageIndex = id;
                QueryData(id);
            }
        }

        private void btnDownWBAll_Click(object sender, RoutedEventArgs e)
        {

            try
            {
                int sid = int.Parse(txtStart.Text);
                int maxNum = int.Parse(txtNum.Text);
                Task.Factory.StartNew(new Action(() =>
                {
                    DownWanbenList(sid, maxNum);
                }));

            }
            catch (Exception ex)
            {
                XTrace.WriteException(ex);
                ShowMessage(ex.Message);
            }
        }
    }
}
